package com.mobile.web.ai;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Service
public class DeepseekService {

    private static final Logger logger = LoggerFactory.getLogger(DeepseekService.class);

    @Value("${deepseek.api.url}")
    private String apiUrl;

    @Value("${deepseek.api.key}")
    private String apiKey;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 初始化OkHttp客户端（单例复用）
    private final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .build();

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 发送请求并获取完整的流式响应
     */
    public String getChatResponse(String userMessage) {
        logger.info("开始发送AI请求，消息长度: {} 字符", userMessage.length());
        
        // 用于等待异步响应完成
        CountDownLatch latch = new CountDownLatch(1);
        StringBuilder fullResponse = new StringBuilder();

        try {
            // 1. 构建请求参数
            logger.debug("构建AI请求参数");
            AIRequest requestBody = new AIRequest();
            requestBody.setStream(true); // 启用流式响应
            requestBody.setMax_tokens(8192); // 最大生成长度
            requestBody.setMessages(Collections.singletonList(
                    new AIRequest.Message("user", userMessage)
            ));

            // 2. 转换为JSON字符串
            String jsonBody = objectMapper.writeValueAsString(requestBody);
            logger.debug("请求JSON构建完成，长度: {} 字符", jsonBody.length());

            // 3. 构建OkHttp请求
            logger.debug("构建HTTP请求，目标URL: {}", apiUrl);
            Request request = new Request.Builder()
                    .url(apiUrl)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", "Bearer " + apiKey)
                    .post(RequestBody.create(
                            MediaType.parse("application/json; charset=utf-8"),
                            jsonBody
                                        ))
                    .build();

            // 4. 异步发送请求并处理流式响应
            logger.info("发送HTTP请求到AI服务");
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    logger.error("AI请求失败: {}", e.getMessage(), e);
                    latch.countDown(); // 无论成功失败，都要释放锁
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        logger.info("收到AI响应，状态码: {}", response.code());
                        if (!response.isSuccessful() || response.body() == null) {
                            logger.error("AI响应失败，状态码: {}", response.code());
                            return;
                        }

                        // 读取流式响应
                        logger.debug("开始读取流式响应");
                        int chunkCount = 0;
                        try (ResponseBody body = response.body()) {
                            okio.BufferedSource source = body.source();
                            while (!source.exhausted()) {
                                String line = source.readUtf8Line();
                                if (line == null || line.trim().isEmpty()) {
                                    continue;
                                }

                                // 处理SSE格式数据（data: 开头）
                                if (line.startsWith("data: ")) {
                                    String data = line.substring(6).trim();
                                    // 检查结束标记
                                    if ("[DONE]".equals(data)) {
                                        logger.debug("收到流式响应结束标记");
                                        break;
                                    }
                                    // 解析JSON获取内容
                                    JsonNode node = objectMapper.readTree(data);
                                    String content = node.at("/choices/0/delta/content").asText("");
                                    if (!content.isEmpty()) {
                                        fullResponse.append(content);
                                        chunkCount++;
                                        if (chunkCount % 10 == 0) {
                                            logger.debug("已接收 {} 个响应块，当前响应长度: {} 字符", 
                                                       chunkCount, fullResponse.length());
                                        }
                                    }
                                }
                            }
                        }
                        logger.info("流式响应读取完成，总共接收 {} 个响应块，最终响应长度: {} 字符", 
                                   chunkCount, fullResponse.length());
                    } catch (Exception e) {
                        logger.error("处理AI响应出错: {}", e.getMessage(), e);
                    } finally {
                        response.close();
                        latch.countDown(); // 释放锁，通知等待线程
                    }
                }
            });

            // 等待响应完成（最多等待5分钟，防止无限阻塞）
            logger.debug("等待AI响应完成，最大等待时间: 15分钟");
            boolean completed = latch.await(15, TimeUnit.MINUTES);
            if (!completed) {
                logger.error("AI请求超时，未能在15分钟内获取完整响应");
                return "超时：未能在15分钟内获取完整响应";
            }

        } catch (Exception e) {
            logger.error("处理AI请求时发生错误: {}", e.getMessage(), e);
            return "处理请求时发生错误: " + e.getMessage();
        }

        String result = fullResponse.length() > 0 ? fullResponse.toString() : "未获取到有效响应";
        logger.info("AI请求完成，返回响应长度: {} 字符", result.length());
        return result;
    }

    /**
     * 查询数据库中所有现有的工单号
     * @return 工单号列表
     */
    private List<String> getExistingWorkOrderNumbers() {
        logger.debug("开始查询数据库中现有的工单号");
        try {
            String sql = "SELECT WORK_ORDER_NO FROM b_work_order";
            List<String> workOrderNumbers = jdbcTemplate.queryForList(sql, String.class);
            logger.info("查询到 {} 个现有工单号", workOrderNumbers.size());
            return workOrderNumbers;
        } catch (Exception e) {
            logger.error("查询现有工单号失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    /**
     * 构建包含现有工单号信息的完整提示词
     * @return 完整的提示词
     */
    private String buildPromptWithExistingWorkOrders() {
        logger.debug("开始构建包含现有工单号的提示词");
        
        // 获取基础prompt
        String basePrompt = getPrompt();
        if (basePrompt.isEmpty()) {
            logger.error("未能读取到基础prompt内容");
            return "";
        }
        
        // 获取现有工单号
        List<String> existingWorkOrderNumbers = getExistingWorkOrderNumbers();
        
        // 构建工单号约束信息
        StringBuilder workOrderConstraint = new StringBuilder();
        workOrderConstraint.append("\n\n【重要约束条件】\n");
        workOrderConstraint.append("数据库中已存在以下工单号，生成新的工单数据时，WORK_ORDER_NO字段不允许与以下工单号重复：\n");
        
        if (existingWorkOrderNumbers.isEmpty()) {
            workOrderConstraint.append("当前数据库中暂无工单数据，可以从头开始生成。\n");
        } else {
            workOrderConstraint.append("现有工单号列表：\n");
            for (String workOrderNo : existingWorkOrderNumbers) {
                workOrderConstraint.append("- ").append(workOrderNo).append("\n");
            }
        }
        
        workOrderConstraint.append("\n请确保生成的工单号具有唯一性，建议使用以下格式：\n");
        workOrderConstraint.append("- 养老保险工单：YL + 年月日 + 4位序号（如：YL202501270001）\n");
        workOrderConstraint.append("- 失业保险工单：SY + 年月日 + 4位序号（如：SY202501270001）\n");
        workOrderConstraint.append("- 工伤保险工单：GS + 年月日 + 4位序号（如：GS202501270001）\n");
        workOrderConstraint.append("请严格避免生成重复的工单号！\n");
        
        // 将约束条件添加到基础prompt之后
        String fullPrompt = basePrompt + workOrderConstraint.toString();
        
        logger.info("构建完整提示词成功，总长度: {} 字符，包含 {} 个现有工单号", 
                   fullPrompt.length(), existingWorkOrderNumbers.size());
        
        return fullPrompt;
    }

    /**
     * 应用启动时立即执行一次
     */
    // @PostConstruct
    public void runOnStartup() {
        logger.info("应用启动，立即执行一次SQL生成任务");
        createOrderTask(); // 调用定时任务的方法
    }
    
    @Scheduled(cron = "0 25 11 * * *")
    public void createOrderTask() {
        logger.info("开始执行定时SQL生成任务");
        
        // 构建包含现有工单号信息的完整提示词
        logger.debug("构建包含现有工单号约束的AI请求prompt");
        String prompt = buildPromptWithExistingWorkOrders();
        if (prompt.isEmpty()) {
            logger.error("未能构建完整的prompt内容，任务终止");
            return;
        }
        
        logger.info("发送给AI的prompt长度: {} 字符", prompt.length());
        logger.debug("开始调用AI生成SQL");
        String sqlResult = getChatResponse(prompt);
        logger.info("AI生成SQL完成，结果长度: {} 字符", sqlResult.length());
        logger.debug("生成的SQL语句:\n{}", sqlResult);
        
        // 执行生成的SQL语句
        logger.info("开始执行生成的SQL语句");
        executeSql(sqlResult);
        logger.info("定时SQL生成任务执行完成");
    }
    
    /**
     * 执行SQL语句
     * @param sql 要执行的SQL语句
     */
    public void executeSql(String sql) {
        logger.info("开始执行SQL语句，总长度: {} 字符", sql.length());
        
        try {
            // 分割多条SQL语句（假设每条SQL语句以分号结尾）
            String[] sqlStatements = sql.split(";");
            logger.info("SQL分割完成，共 {} 条语句", sqlStatements.length);
            
            int executedCount = 0;
            for (int i = 0; i < sqlStatements.length; i++) {
                String statement = sqlStatements[i].trim();
                if (!statement.isEmpty()) {
                    logger.debug("执行第 {} 条SQL: {}", i + 1, statement);
                    try {
                        jdbcTemplate.execute(statement + ";");
                        executedCount++;
                        logger.debug("第 {} 条SQL执行成功", i + 1);
                    } catch (Exception e) {
                        logger.error("第 {} 条SQL执行失败: {}, SQL: {}", i + 1, e.getMessage(), statement);
                        // 继续执行下一条SQL，不中断整个流程
                    }
                }
            }
            logger.info("SQL执行完成，成功执行 {} 条语句，总共 {} 条语句", executedCount, sqlStatements.length);
        } catch (Exception e) {
            logger.error("执行SQL出错: {}", e.getMessage(), e);
        }
    }

    /**
     * 读取prompt.txt文件内容
     */
    public String getPrompt() {
        logger.debug("开始读取prompt.txt文件");
        try {
            // 使用类路径资源加载器读取文件
            ClassPathResource resource = new ClassPathResource("static/prompt.txt");
            String content = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8);
            logger.info("prompt.txt文件读取成功，内容长度: {} 字符", content.length());
            return content;
        } catch (IOException e) {
            logger.error("读取prompt文件失败: {}", e.getMessage(), e);
            return "";
        }
    }
}
